package com.hexb.core.mybatis

import com.google.common.base.CaseFormat
import com.hexb.core.annotation.Column
import com.hexb.core.annotation.Id
import com.hexb.core.annotation.InsertIgnore
import com.hexb.core.annotation.Table
import com.hexb.core.annotation.UpdateIgnore
import com.hexb.core.model.enums.IDType
import com.hexb.core.mybatis.entry.ColumnEntry
import com.hexb.core.mybatis.entry.IdEntry
import com.hexb.core.mybatis.entry.MapperEntry
import com.hexb.core.mybatis.entry.SqlEntry
import com.hexb.core.utils.ReflectionHelper
import org.apache.ibatis.mapping.ResultMapping
import org.apache.ibatis.session.Configuration
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.core.annotation.AnnotationUtils

/**
 * @Package : com.hexb.mt.config
 * @Author : hexb 
 * @Date : 2018-08-11 15:01
 * 从实体或注解中获取SQL必要元素
 */
class SqlEntryBuilder {

    static private Logger logger = LoggerFactory.getLogger(SqlEntryBuilder.class)

    static SqlEntry toSqlBuildEntry(MapperEntry t, Configuration configuration) {
        def entry
        try {
            Class<?> entryClazz = Class.forName(t.entryType)
            Table tableAnnotation = AnnotationUtils.findAnnotation(entryClazz, Table.class)
            //获取表名
            //是否需要驼峰转下划线
            //1.project.entryToTableCamelToUnderscore = true
            //2.mybatis.mapUnderscoreToCamelCase = true
            String tableName = tableAnnotation && tableAnnotation.value() ?
                    tableAnnotation.value() :
                    (BaseMapperConfiguration.projectProperties.entryToTableCamelToUnderscore || configuration.mapUnderscoreToCamelCase ?
                            CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entryClazz.simpleName) : entryClazz.simpleName)

            String orderBy = tableAnnotation ? tableAnnotation.orderBy() : null

            entry = new SqlEntry(
                    tableName: tableName,
                    namespace: t.mapperName,
                    entryClass: entryClazz,
                    orderBy: orderBy
            )

            if (tableAnnotation && entry.idEntry) {
                entry.idEntry.idType = tableAnnotation.idType() ?: IDType.AUTO_INCREMENT
            }

            def fields = ReflectionHelper.getClassFields(entryClazz)
            fields.each {

                Column column = AnnotationUtils.findAnnotation(it, Column.class)
                String columnName = column && column.value() ? column.value() : it.name

                Id id = AnnotationUtils.findAnnotation(it, Id.class)
                String idColumn
                if (id) {
                    idColumn = id && id.value() ? id.value() : it.name
                    entry.idEntry = new IdEntry(
                            property: it.name,
                            column: idColumn,
                            idClass: Class.forName(t.pkType),
                            idType: tableAnnotation.idType() ?: IDType.AUTO_INCREMENT
                    )
                }

                if (idColumn) {
                    columnName = idColumn
                }

                InsertIgnore insertIgnore = AnnotationUtils.findAnnotation(it, InsertIgnore.class)
                boolean bInsertIgnore = insertIgnore != null || (!it.type.name.startsWith('java') && !it.type.isEnum())

                UpdateIgnore updateIgnore = AnnotationUtils.findAnnotation(it, UpdateIgnore.class)
                boolean bUpdateIgnore = updateIgnore != null || (!it.type.name.startsWith('java') && !it.type.isEnum())

                entry.propertyMapping << new ColumnEntry(it.name, columnName, bInsertIgnore, bUpdateIgnore)

                if (column) {
                    Class<?> javaType = column.javaType() ? Class.forName(column.javaType()) : it.type
                    entry.resultMappings << new ResultMapping.Builder(configuration, it.name, columnName, javaType).build()
                }
            }
        } catch (e) {
            logger.error(e)
        }
        entry
    }

}
